/*
 * frameInt.c - 帧中断驱动
 */

#include <vxWorks.h>
#include <vsbConfig.h>
#include <intLib.h>
#include <errnoLib.h>
#include <errno.h>
#include <sioLib.h>
#include <ioLib.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <vxAtomicLib.h>
#include <semLib.h>
#include <sysLib.h>
#include <vmLib.h>
#include <hwif/vxBus.h>
#include <hwif/buslib/vxbFdtLib.h>
#include <taskLib.h>
#include "frameInt.h"

static STATUS frameIntInited = ERROR;

/* VxBus方法 */
LOCAL STATUS frameIntProbe(VXB_DEV_ID);
LOCAL STATUS frameIntAttach(VXB_DEV_ID);

LOCAL VXB_DRV_METHOD frameIntMethods[] = {
    { VXB_DEVMETHOD_CALL(vxbDevProbe), frameIntProbe },
    { VXB_DEVMETHOD_CALL(vxbDevAttach), frameIntAttach },
    VXB_DEVMETHOD_END
};

VXB_DRV frameIntDrv = {
    { NULL },
    FRAME_INT_NAME,         /* 驱动名称 */
    "Frame Interrupt driver", /* 描述 */
    VXB_BUSID_FDT,          /* 总线类型 */
    0,                      /* 标志 */
    0,                      /* 引用计数 */
    frameIntMethods          /* 方法表 */
};

/* 设备树匹配表 */
LOCAL VXB_FDT_DEV_MATCH_ENTRY frameIntMatch[] = {
    { "dd,fdtinterrupt", (void *)NULL },
    {} /* 空终止列表 */
};

/* 设备打开函数 */
void frameIntOpen(VXB_DEV_ID *ppDev, UINT32 unit) {
    if(frameIntInited == ERROR)
        frameIntInited = vxbDrvAdd(&frameIntDrv);
    
    if(frameIntInited == OK)
        *ppDev = vxbDevAcquireByName(FRAME_INT_NAME, unit);
}

/* 设备关闭函数 */
int frameIntClose(VXB_DEV_ID pDev) {
    return OK;
}

void ddRegSet(UINT32 offset, UINT32 val);
/* 中断处理函数 */
void frameIntHandler(FRAME_INT_DRV_CTRL *pDrvCtrl) {
    /* 处理中断逻辑 */
     ddRegSet(0x10024, 0);
    logMsg("frameIntHandler\n",1,2,3,4,5,6);

}
/* 探测函数 */
LOCAL STATUS frameIntProbe(VXB_DEV_ID pDev) {
    return vxbFdtDevMatch(pDev, frameIntMatch, NULL);
}
LOCAL STATUS frameIntAttach(VXB_DEV_ID pDev) {
    FRAME_INT_DRV_CTRL *pDrvCtrl; 
    char *pname = NULL;
    int proplen = 0;

    /* 分配驱动控制结构 */
    pDrvCtrl = vxbMemAlloc(sizeof(FRAME_INT_DRV_CTRL));
    if(pDrvCtrl == NULL) {
        return ERROR;
    }
    bzero((char *)pDrvCtrl, sizeof(FRAME_INT_DRV_CTRL));
    vxbDevSoftcSet(pDev, pDrvCtrl);
    pDrvCtrl->frameIntDev = pDev;

    /* 获取中断资源 */
    pDrvCtrl->intRes = vxbResourceAlloc(pDev, VXB_RES_IRQ, 0);
    if(pDrvCtrl->intRes == NULL) {
        logMsg("Failed to get Irq resource!\n", 0, 0, 0, 0, 0, 0);
        goto Exit;
    }
 

    /* 创建信号量 */
    pDrvCtrl->frameIntSem = semMCreate(SEM_Q_PRIORITY | SEM_DELETE_SAFE | SEM_INVERSION_SAFE);

    /* 注册中断处理程序 */
    if(OK != vxbIntConnect(pDev, pDrvCtrl->intRes, (VOIDFUNCPTR)frameIntHandler, (int)pDrvCtrl)) {
        logMsg("Failed to connect interrupt of device %s\n", (int)FRAME_INT_NAME, 0, 0, 0, 0, 0);
        goto Exit;
    }
    
    if(OK != vxbIntEnable(pDev, pDrvCtrl->intRes)) {
        logMsg("Failed to enable interrupt of device %s\n", (int)FRAME_INT_NAME, 0, 0, 0, 0, 0);
        vxbIntDisconnect(pDev, pDrvCtrl->intRes);
        goto Exit;
    }

    return OK;

Exit:
    if(pDrvCtrl != NULL) {
        free(pDrvCtrl);
    }
    return ERROR;
}
